package seven;

import com.seven.pojo.Evection;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.junit.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ActivitiDemo {
    /**
     * 部署流程定义
     */
    @Test
    public void testDeployment() {
        // 1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2、得到RepositoryService实例
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 3、使用RepositoryService进行部署
        Deployment deployment = repositoryService.createDeployment()
                // 添加bpmn资源
                .addClasspathResource("bpmn/Leave.bpmn20.xml")
                // 添加png资源
                .addClasspathResource("bpmn/Leave.png")
                .name("请假申请流程")
                .deploy();
        System.out.println("流程部署id：" + deployment.getId());
        System.out.println("流程部署名称：" + deployment.getName());
    }

    /**
     * 启动流程实例
     */
    @Test
    public void testStartProcess() {
        // 1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2、获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 3、根据流程定义Id启动流程
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey("Leave");
        System.out.println("流程定义id：" + processInstance.getProcessDefinitionId());
        System.out.println("流程实例id：" + processInstance.getId());
        System.out.println("当前活动Id：" + processInstance.getActivityId());
    }


    /**
     * 查询当前个人待执行的任务
     */
    @Test
    public void testFindPersonalTaskList() throws Exception {
        // 任务负责人
// String assignee = "employee";
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 创建TaskService
        TaskService taskService = processEngine.getTaskService();
        // 根据流程key和任务负责人查询任务
        List<Task> list = taskService.createTaskQuery()
                //流程Key
                .processDefinitionKey("Leave")
                //只查询该任务负责人的任务
//         .taskAssignee(assignee)
                .list();
        for (Task task : list) {
            System.out.println("流程实例id：" + task.getProcessInstanceId());
            System.out.println("任务id：" + task.getId());
            System.out.println("任务负责人：" + task.getAssignee());
            System.out.println("任务名称：" + task.getName());
        }
    }

    // 完成任务
    @Test
    public void completTask() {
        // 获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取taskService
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                // 流程Key
                .processDefinitionKey("Leave")
                // 要查询的负责人
//         .taskAssignee("employee")  
                .singleResult();

        taskService.complete(task.getId());
    }

    /**
     * 查询流程定义
     */
    @Test
    public void queryProcessDefinition() {
        // 获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        List<ProcessDefinition> definitionList = processDefinitionQuery.processDefinitionKey("Leave")
                .orderByProcessDefinitionVersion()
                .desc()
                .list();
        for (ProcessDefinition processDefinition : definitionList) {
            System.out.println("流程定义 id=" + processDefinition.getId());
            System.out.println("流程定义 name=" + processDefinition.getName());
            System.out.println("流程定义 key=" + processDefinition.getKey());
            System.out.println("流程定义 Version=" + processDefinition.getVersion());
            System.out.println("流程部署ID =" + processDefinition.getDeploymentId());
        }
    }

    /**
     * 查询流程实例
     */
    @Test
    public void queryProcessInstance() {
        // 流程定义key
        String processDefinitionKey = "Leave";
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        List<ProcessInstance> list = runtimeService
                .createProcessInstanceQuery()
                .processDefinitionKey(processDefinitionKey)//
                .list();

        for (ProcessInstance processInstance : list) {
            System.out.println("----------------------------");
            System.out.println("流程实例id："
                    + processInstance.getProcessInstanceId());
            System.out.println("所属流程定义id："
                    + processInstance.getProcessDefinitionId());
            System.out.println("是否执行完成：" + processInstance.isEnded());
            System.out.println("是否暂停：" + processInstance.isSuspended());
            System.out.println("当前活动标识：" + processInstance.getActivityId());
            System.out.println("业务关键字：" + processInstance.getBusinessKey());
        }
    }

    /**
     * 查看历史信息
     */
    @Test
    public void findHistoryInfo() {
        // 获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取HistoryService
        HistoryService historyService = processEngine.getHistoryService();
        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
        instanceQuery.processInstanceId("2501");
        instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
        List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
        for (HistoricActivityInstance hi : activityInstanceList) {
            System.out.println("============="+hi.getActivityId()+" START=============");
            System.out.println(hi.getActivityId());
            System.out.println(hi.getActivityName());
            System.out.println(hi.getProcessDefinitionId());
            System.out.println(hi.getProcessInstanceId());
            System.out.println("============="+hi.getActivityId()+" END=============");
        }
    }

    @Test
    public void downBpmnFile() throws IOException {
        // 1、得到引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2、获取repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 3、得到查询器：ProcessDefinitionQuery
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("Leave")
                .singleResult();
        // 4、通过流程定义信息，得到部署ID
        String deploymentId = processDefinition.getDeploymentId();
        // 5、通过repositoryService的方法，实现读取图片信息和bpmn信息
         InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName());
        // bpmn文件的流
        InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, processDefinition.getResourceName());
        File file_png = new File("d:/Leave.png");
        File file_bpmn = new File("d:/Leave.bpmn20.xml");
        FileOutputStream bpmnOut = new FileOutputStream(file_bpmn);
        FileOutputStream pngOut = new FileOutputStream(file_png);
        IOUtils.copy(pngInput, pngOut);
        IOUtils.copy(bpmnInput, bpmnOut);
        pngOut.close();
        bpmnOut.close();
        pngInput.close();
        bpmnInput.close();
    }


    /**
     * 添加业务key
     */
    @Test
    public void addBusinessKey() {
        // 1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2、获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 3、启动流程的过程中，添加businesskey
        ProcessInstance instance = runtimeService.
                startProcessInstanceByKey("Leave", "businessNo");
        System.out.println("businessKey==" + instance.getBusinessKey());

    }

    //=================流程变量相关代码 start===============//

    /**
     * 启动流程的时候设置流程变量
     */
    @Test
    public void testStartProcessAndSetVariables() {
        // 1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2、获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 3、流程定义的Key
        String key = "Leave";
        // 4、流程变量的map
        Map<String, Object> variables = new HashMap<>();
        // 5、设置流程变量
        Evection evection = new Evection();
        // 6、设置请假日期
        evection.setDay(2d);
        // 7、把流程变量的pojo放入map
        variables.put("evection", evection);
        // 8、设定任务的负责人
        variables.put("employee", "小七");
        variables.put("TeamLeader", "第七人格");
        variables.put("Manager", "老李");
        // 9、启动流程
        runtimeService.startProcessInstanceByKey(key, variables);
    }

    /**
     * 完成个人任务
     */
    @Test
    public void completTaskByVariables() {
        completTaskByVariables("小七");
        completTaskByVariables("第七人格");
        completTaskByVariables("老李");
    }

    private void completTaskByVariables(String assingee) {
        // 1、流程定义的Key
        String key = "Leave";
        // 2、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 3、获取taskService
        TaskService taskService = processEngine.getTaskService();
        // 4、查询任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskAssignee(assingee)
                .singleResult();
        if (task != null) {
            taskService.complete(task.getId());
            System.out.println(task.getId() + "----任务负责人：" + task.getAssignee() + "----任务已完成");
        }
    }

    //=================任务组相关代码 start===============//

    /**
     * 启动流程的时候设置流程变量
     */
    @Test
    public void testStartProcessAndSetVariablesAboutGroup() {
        // 1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2、获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 3、流程定义的Key
        String key = "Leave";
        // 4、流程变量的map
        Map<String, Object> variables = new HashMap<>();
        // 5、设置流程变量
        Evection evection = new Evection();
        // 6、设置请假日期
        evection.setDay(2d);
        // 7、把流程变量的pojo放入map
        variables.put("evection", evection);
        // 8、设定任务的负责人
        variables.put("employee", "小七");
        variables.put("Manager", "老李");
        // 9、启动流程
        runtimeService.startProcessInstanceByKey(key, variables);
    }

    @Test
    public void completTaskByVariablesAboutGroup() {
        // 测试组任务时，只执行这一行代码
        completTaskByVariables("小七");
    }

    /**
     * 查询组任务
     */
    @Test
    public void findGroupTaskList() {
        // 1、流程定义的Key
        String key = "Leave";
        // 2、任务候选人
        String candidateUser = "组长1";
        // 3、获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 4、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        // 5、查询组任务
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey(key)
                // 根据候选人查询任务
                .taskCandidateUser(candidateUser)
                .list();
        for (Task task : taskList) {
            System.out.println("============查询组任务============");
            System.out.println("流程实例ID=" + task.getProcessInstanceId());
            System.out.println("任务id=" + task.getId());
            System.out.println("任务名称：" + task.getName());
            System.out.println("任务负责人=" + task.getAssignee());
        }
    }

    /**
     * 候选人绑定任务
     */
    @Test
    public void claimTask() {
        // 1、获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        // 3、当前任务的id
        String taskId = "5002";
        // 4、任务候选人
        String candidateUser = "组长1";
        // 5、查询任务
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskCandidateUser(candidateUser)
                .singleResult();
        if (task != null) {
            // 6、绑定任务
            taskService.claim(taskId, candidateUser);
            System.out.println("taskId-" + taskId + "-用户-" + candidateUser + "-绑定任务完成");
        }
    }

    /**
     * 候选人归还任务
     */
    @Test
    public void testAssigneeToGroupTask() {
        // 1、获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        // 3、当前任务的id
        String taskId = "5002";
        // 4、任务负责人
        String assignee = "组长1";
        // 5、根据key 和负责人来查询任务
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskAssignee(assignee)
                .singleResult();
        if (task != null) {
            // 6、归还任务 ,就是把负责人设置为空
            taskService.setAssignee(taskId, null);
            System.out.println("taskId-" + taskId + "-用户-" + assignee + "-归还任务完成");
        }
    }

}
